#ifndef _MY_SCENE_H_
#define _MY_SCENE_H_

#include "cse452.h"
#include "Color.h"
#include "camera/Camera.h"
#include "parser.h"
#include "Light.h"
#include <FL/Fl_Image.H>
#include <string>
#include <vector>
#include <map>
#include "Subgraph.h"
#include "../Shapes/Shape.h"

/*
 * This class holds all of the data in the scene file.
 *  Camera
 *  Lights
 *  Subgraphs
 *  Root subgraph
 */

// ToDo: Define these
class Object;
class Node;
class Tree;

class MyScene {
public:
    MyScene();
    ~MyScene();

    // The start of the parsing routine
    // Called once when a new scene file is opened
    bool loadSceneFile(std::string filename);

    // Return the current error mesage (if any) generated by parsing
    std::string getErrorMessage() const;

    // Return the parsed camera
    Camera &changeCamera();

    // Return the parsed camera
    const Camera &getCamera() const;

    // Return the parsed camera
    const Color &getBackground() const;

    // Called when the window is re-sized
    void resize(int w, int h);
    // Called when the window needs to be re-drawn
    // Stub can be found in sceneview/MyScene_draw.cpp
    void draw();
    
    /* 
     * The following are for the user interaction assignment 
     * Stubs for them can be found in Interactive/MySceneSelect.cpp
     */
    // User clicked on the screen; find the corresponding shape
    bool selectNode(int x, int y);
    //
    void moveSelectedNode( const Matrix4 &matChange );
    
    /*
     * The following are for the ray tracing assignment
     * Stubs for them can be found in rendering/MyScene_render.cpp
     */
    // 
    void render(int type, int width, int height, unsigned char* pixels);
    void stopRender();
    double getRenderProgress();

	inline void MyScene::putPixel(int x, int y, const Color & col, unsigned char* pixels);

	const static int RECURSE_DEPTH = 6;

	Hit rayToObject(const Vector3 ray, const Point3 point, MatrixObject*& hitObject);
	void renderScanline(int width, int height, unsigned char* pixels);
	void lightAtPoint(const int x, const int y, unsigned char& r, unsigned char& g, unsigned char& b, const int depth=RECURSE_DEPTH);
	void lightAlongRay(const Vector3& ray, const Point3& point, unsigned char& r, unsigned char& g, unsigned char& b, const int levels=0);
	void renderRayTracing(int width, int height, unsigned char* pixels);

	double progress;


	int renderWidth;
	bool stopRendering;


    /*
     * The following are for the sceneview assignment
     * They can be found in sceneview/MyScene.cpp
     */
    // Clear out any existing data
    void resetScene();

    // Gets the background color from the scenefile
    bool parseBackground(Parser& p);

    // Gets the camera info (if any) from the scene file
    bool parseCamera(Parser& p);

    // Gets the light info (if any) from the scene file
    bool parseLight(Parser& p);

    /*
     * The following are the parsing routines you need to finish filling in.
     * Feel free to change the return type or pass in additional parameters.
     */
    // Called when subgraph _name_ [ is encountered in the scene file
    // Should return true when root subgraph encountered
    Subgraph* parseMasterSubgraph(Parser& p);

    // Called when trans [ is encountered
    Trans* parseTrans(Parser& p);

    // Called when Object _name_ [ is encountered
    Object* parseObject(Parser& p);
  
	int getWidth(){return camera.getWidth();}
	int getHeight(){return camera.getHeight();}

	std::list<MatrixObject>* getObjectList(){return &objectList;}

	Vector3 makeRay(double x, double y);

private:
    // Has loadSceneFile been called yet?
    bool isLoaded;
    // Keep track of the current error message
    std::string errorMessage;
    
    // Store camera info; remember that your default camera should be
    // set to reasonable values in case there is no camera information
    // in the scene file
    Camera camera;

    // Stores the background color found in the scenefile (if any).
    // Defaults to black
    Color background;

    // The stored lights
    Color ambientLight;
    std::vector<Light> lights;

    // your functions/variables go here
	std::map<std::string, Subgraph*> masterSubgraphs;
	Shape* cube;
	Shape* sphere;
	Shape* cylinder;
	Shape* cone;

	
	std::list<MatrixObject> objectList;
	
};

#endif /* _MY_SCENE_H_ */
